package com.qys.livesMall.shop.service.impl;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.app.user.constants.RedisConstant;
import com.qys.livesMall.app.user.enums.SmsEnum;
import com.qys.livesMall.app.user.mapper.AppUserLevelMapper;
import com.qys.livesMall.app.user.mapper.H2AppUserMapper;
import com.qys.livesMall.app.user.model.entity.AppUserLevel;
import com.qys.livesMall.app.user.model.entity.H2AppUser;
import com.qys.livesMall.app.user.service.AppUserRelationService;
import com.qys.livesMall.app.user.service.IH2AppUserService;
import com.qys.livesMall.app.user.service.IpOperateStatisticsService;
import com.qys.livesMall.app.user.utils.SmsUtil;
import com.qys.livesMall.cache.RedisCache;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.enums.LanguageEnum;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.exception.enums.ExceptionEnum;
import com.qys.livesMall.common.message.MessageServer;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.common.utils.bean.BeanProUtils;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.model.dto.shop.AddShopAccount;
import com.qys.livesMall.finance.model.entity.shop.FinanceShopAccount;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.finance.service.FinanceShopAccountService;
import com.qys.livesMall.finance.util.BusinessNoUtil;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.Paging;
import com.qys.livesMall.framework.view.QysPage;
import com.qys.livesMall.open.enums.PushMessageTypeEnum;
import com.qys.livesMall.open.mail.AsyncMailClient;
import com.qys.livesMall.open.mail.modal.MailM;
import com.qys.livesMall.open.modal.dto.app.PushUserDeviceContentDTO;
import com.qys.livesMall.open.modal.dto.mail.PushAllDeviceDTO;
import com.qys.livesMall.open.modal.dto.mail.PushTitleDTO;
import com.qys.livesMall.open.service.PushUserDeviceService;
import com.qys.livesMall.shop.constants.ShopConstant;
import com.qys.livesMall.shop.dao.H2ShopBaseDao;
import com.qys.livesMall.shop.dao.H2ShopContractDao;
import com.qys.livesMall.shop.dao.H2ShopLevelDao;
import com.qys.livesMall.shop.dao.H2ShopLevelRecordDao;
import com.qys.livesMall.shop.enums.ShopMessageEnum;
import com.qys.livesMall.shop.mapper.H2ShopBaseMapper;
import com.qys.livesMall.shop.mapper.ShopGoodsInfoMapper;
import com.qys.livesMall.shop.mapper.ShopOrderSkuMapper;
import com.qys.livesMall.shop.modal.dto.CloseShopDto;
import com.qys.livesMall.shop.modal.dto.shop.*;
import com.qys.livesMall.shop.modal.dto.shop.contract.EditContract;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.modal.vo.AppShopVO;
import com.qys.livesMall.shop.modal.vo.ShopVO;
import com.qys.livesMall.shop.service.*;
import com.qys.livesMall.system.model.entity.H2SysConfig;
import com.qys.livesMall.system.service.IH2SysConfigService;
import com.qys.livesMall.system.service.SysLanguageTextService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * 用户小店(H2ShopBase)表服务实现类
 *
 * @author makejava
 * @since 2023-05-26 10:29:44
 */
@Slf4j
@Service
public class H2ShopBaseServiceImpl implements H2ShopBaseService {
    @Resource
    private H2ShopBaseDao h2ShopBaseDao;
    @Resource
    private H2ShopBaseMapper shopBaseMapper;
    @Resource
    private MessageServer messageServer;

    @Autowired
    private H2ShopContractService h2ShopContractService;

    @Autowired
    private H2ShopLevelDao h2ShopLevelDao;

    @Autowired
    private H2ShopLevelService shopLevelService;

    @Autowired
    private H2ShopContractDao contractDao;

    @Autowired
    private IH2AppUserService appUserService;
    @Resource
    private ShopGoodsInfoService shopGoodsInfoService;
    @Resource
    private ShopOrderSkuMapper orderSkuMapper;

    @Resource
    private H2AppUserMapper h2AppUserMapper;

    @Resource
    private AppUserLevelMapper appUserLevelMapper;

    @Autowired
    private FinanceShopAccountService financeShopAccountService;

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private RedisCache redisCache;
    @Resource
    private PushUserDeviceService pushUserDeviceService;
    @Resource
    private AsyncMailClient asyncMailClient;

    @Autowired
    private FinanceBusinessService financeBusinessService;

    @Autowired
    private AppUserRelationService relationService;

    @Autowired
    private H2ShopLevelRecordDao shopLevelRecordDao;

    @Autowired
    private IH2SysConfigService sysConfigService;

    @Resource
    private H2ShopStatisticsInfoService shopStatisticsInfoService;

    @Resource
    private ShopStatisticsTeamService shopStatisticsTeamService;

    @Resource
    private IpOperateStatisticsService ipOperateStatisticsService;

    @Resource
    private ShopGoodsSkuStocksService shopGoodsSkuStocksService;

    @Resource
    private SysLanguageTextService languageTextService;
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public H2ShopBase queryById(Long id) {
        return this.h2ShopBaseDao.getById(id);
    }

    /**
     * 通过ID查询单条数据
     *
     * @param shopId 主键
     * @return 实例对象
     */
    @Override
    public AppShopVO queryByShopId(Long shopId) {
        H2ShopBase shop = h2ShopBaseDao.getById(shopId);
        AppShopVO shopVO= BeanProUtils.copyProperties(shop, AppShopVO::new);
        H2ShopLevel level=h2ShopLevelDao.getById(shop.getShopLevelId());
        if (level!=null) {
            shopVO.setShopLevel(level.getName());
            shopVO.setCashBeforeDelivery(Integer.valueOf(level.getCashBeforeDelivery()));
            shopVO.setDeliveryBeforeCash(Integer.valueOf(level.getDeliveryBeforeCash()));
        }
        //获取店铺销量
        H2ShopStatisticsInfo info= shopStatisticsInfoService.getField(shopId,H2ShopStatisticsInfo::getId, H2ShopStatisticsInfo::getSalesVolume);
        if (info!=null) {
            shopVO.setShopSalesVolume(info.getSalesVolume());
        }
        return shopVO;
    }

    /**
     * 通过ID查询单条数据
     *
     * @param userId y用户编号
     * @return 实例对象
     */
    @Override
    public H2ShopBase queryShopBaseByUserId(Long userId) {
        H2ShopBase shopBase = h2ShopBaseDao.getByUserId(userId);
        if (null == shopBase) {
            throw new QysException(ShopMessageEnum.SHOP_NOT_EXIST);
        }
        return shopBase;
    }

    @Override
    public Long queryShopBaseIdByUserId(Long userId) {
        Long shopBaseId = h2ShopBaseDao.queryShopBaseIdByUserId(userId);
        if (null == shopBaseId) {
            throw new QysException(ShopMessageEnum.SHOP_NOT_EXIST);
        }
        return shopBaseId;
    }

    @Override
    public AppShopVO getByApp() {
        H2ShopBase shop = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (null == shop){
            return null;
        }
        AppShopVO shopVO= BeanProUtils.copyProperties(shop, AppShopVO::new);
        H2ShopLevel level=h2ShopLevelDao.getById(shop.getShopLevelId());
        if (level!=null) {
            shopVO.setShopLevel(level.getName());
        }
        return shopVO;
    }


    @Override
    public ShopVO get() {
        H2ShopBase shop = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (null == shop){
            return null;
        }
        ShopVO shopVO= BeanProUtils.copyProperties(shop, ShopVO::new);
        H2ShopLevel level=h2ShopLevelDao.getById(shop.getShopLevelId());
        if (level!=null) {
            shopVO.setShopLevel(level.getName());
        }
        return shopVO;
    }

    @Override
    public QysPage<H2ShopBase> search(ShopSearch search){
        Paging paging = new Paging<>(search);
        paging.addOrder(OrderItem.desc("create_time"));

        Paging<H2ShopBase> sPage = shopBaseMapper.search(paging);
        if (CollectionUtils.isEmpty(sPage.getRecords())) {
            return QysPage.build(search);
        }
        return QysPage.to(sPage);
    }

    /**
     * 分页查询
     * ;new Paging<H2ShopBase,ShopSearch>(search)
     *
     * @param search 筛选条件
     * @return 查询结果
     */
    @Override
    public QysPage<ShopVO> list(ShopSearch search) {
        List<H2AppUser> users;
        if (StringUtils.isNotBlank(search.getUserName())) {
            LambdaQueryWrapper<H2AppUser> userQuery = Wrappers.lambdaQuery(H2AppUser.class)
                    .like(H2AppUser::getUserName, search.getUserName())
                    .eq(H2AppUser::getDeleted, 0);
            users = appUserService.list(userQuery);
            List<String> userIds = users.stream().map(H2AppUser::getId).distinct().collect(Collectors.toList());
            search.setUserIds(CollectionUtils.isEmpty(userIds) ? null : userIds);
        }

        Paging paging = new Paging<>(search);
        paging.addOrder(OrderItem.desc("create_time"));

        Paging<H2ShopBase> sPage = shopBaseMapper.search(paging);
        if (CollectionUtils.isEmpty(sPage.getRecords())) {
            return QysPage.build(search);
        }
        List<Integer> ids = sPage.getRecords().stream().map(H2ShopBase::getShopLevelId).collect(Collectors.toList());
        List<H2ShopLevel> levels = h2ShopLevelDao.listByIds(ids);
        Map<Integer, H2ShopLevel> levelMap = null;
        if (CollectionUtils.isEmpty(levels)) {
            levelMap = new HashMap<>();
        } else {
            levelMap = levels.stream().collect(Collectors.toMap(H2ShopLevel::getId, v -> v));
        }
        //余额
        List<Long> shopIds = sPage.getRecords().stream().map(H2ShopBase::getId).collect(Collectors.toList());
        List<FinanceShopAccount> balances = financeShopAccountService.liatByShopIds(shopIds);
        Map<Long, FinanceShopAccount> balanceMap = null;
        if (CollectionUtils.isEmpty(balances)) {
            balanceMap = new HashMap<>();
        } else {
            balanceMap = balances.stream().collect(Collectors.toMap(FinanceShopAccount::getShopId, v -> v));
        }
        //获取用户信息
        List<Long> userIds = sPage.getRecords().stream().map(H2ShopBase::getUserId).collect(Collectors.toList());
        users = appUserService.listByIds(userIds);
        Map<String, H2AppUser> userMap = users.stream().collect(Collectors.toMap(H2AppUser::getId, a->a, (v1, v2) -> v2));

        List<ShopVO> vos = new ArrayList<>();
        Map<Long, FinanceShopAccount> finalBalanceMap = balanceMap;
        Map<Integer, H2ShopLevel> finalLevelMap = levelMap;
        sPage.getRecords().stream().forEach(o -> {
            ShopVO vo = BeanProUtils.copyProperties(o, ShopVO::new);
            vo.setShopLevel(finalLevelMap.get(o.getShopLevelId()) != null ? finalLevelMap.get(o.getShopLevelId()).getName() : null);
            vo.setAvailableBalance(finalBalanceMap.get(o.getId()) != null ? finalBalanceMap.get(o.getId()).getAvailableBalance() : null);
            if (null != o.getUserId()) {
                H2AppUser user= userMap.get(o.getUserId().toString());
                if (null != user){
                    vo.setUserName(user.getUserName());
                    vo.setEmail(user.getEmail());
                }
            }
            vos.add(vo);
        });
        QysPage res = QysPage.build(search);
        res.setRecords(vos).setTotal(sPage.getTotal());
        return QysPage.build(search).setRecords(vos).setTotal(sPage.getTotal());
    }

    /**
     * 修改数据
     *
     * @param editShop 实例对象
     * @return 实例对象
     */
    @Override
    public R update(EditShop editShop) {
        H2ShopBase shop = h2ShopBaseDao.getById(editShop.getId());
        if (shop == null) {
            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);//店铺不存在
        }
        BeanUtils.copyProperties(editShop, shop);
        h2ShopBaseDao.updateById(shop);
        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Long> add(AppAddShop params,String ip) {
        if (params.getName() == null) {
            throw new QysException(ExceptionEnum.PARAM_IS_ERROR);
        }

//        判断是有拥有开店的权限
        H2AppUser h2AppUser = h2AppUserMapper.selectById(SecurityUtils.getUserId());
        Long levelId = h2AppUser.getUserLevelId();
        if (null == levelId) {
//          没有用户等级
            throw new QysException(MessageUtils.message("user.level.lack"));
        }
        AppUserLevel appUserLevel = appUserLevelMapper.selectById(levelId);
        if (null == appUserLevel) {
//         用户等级信息异常
            throw new QysException(MessageUtils.message("level.info.error"));
        }
        if (1 != appUserLevel.getOpenShopFlag()) {
//         没有开店权限
            throw new QysException(MessageUtils.message("shop.open.permission.lack"));
        }
/*        H2SysConfig h2SysConfig=ih2SysConfigService.getConfigByKey("is_open_phone_check");
        if (null != h2SysConfig && h2SysConfig.getValue().equals("true")) {*/
            if (null != params.getPhone() && null != params.getPhoneCode()){
                SmsUtil.verifyCode(SmsEnum.SHOP_APPLY,params.getPhone(), params.getPhoneCode());
            }
//        }
        if (null != params.getEmail() && null != params.getEmailCode()){
            if (!"666665".equals(params.getEmail())){
                String emailCode= redisCache.getCacheObject(RedisConstant.MAILSHOPPHONE + params.getEmail());
                if (!emailCode.equals(params.getEmailCode())){
                    throw new QysException(MessageUtils.message("shop.mail.error"));
                }
            }
        }

        //判断是否申请过小店
        H2ShopBase mallShop = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());

        if (mallShop == null) {
            mallShop = new H2ShopBase();
            BeanProUtils.copyProperties(params, mallShop);
            mallShop.setApplyIp(ip);
            mallShop.setUserId(SecurityUtils.getUserId());
            mallShop.setStatus(ShopConstant.ShopStatus.WAIT_AUDIT);
            mallShop.setApprovalStatus(ShopConstant.AuditStatus.WAIT_AUDIT);
            mallShop.setCreateTime(LocalDateTime.now());

            synchronized (Integer.valueOf(ShopConstant.ShopStatus.WAIT_AUDIT)) {
                Integer maxCode = shopBaseMapper.getShopCodeMax();
                if (null == maxCode){
                    mallShop.setShopCode(10000000);
                }else {
                    mallShop.setShopCode(maxCode + 1);
                }
                boolean save = h2ShopBaseDao.save(mallShop);
                //初始化店铺统计信息
                //生成店铺统计表
                H2ShopStatisticsInfo shopStatisticsInfo=new H2ShopStatisticsInfo();
                shopStatisticsInfo.setShopId(mallShop.getId());
                shopStatisticsInfo.setExpire(Constants.YesNoInt.YES);
                shopStatisticsInfoService.save(shopStatisticsInfo);

                ShopStatisticsTeam team=new ShopStatisticsTeam();
                team.setShopId(mallShop.getId());
                shopStatisticsTeamService.save(team);
            }
        } else {
            BeanProUtils.copyProperties(params, mallShop);
            mallShop.setUserId(SecurityUtils.getUserId());
            mallShop.setStatus(ShopConstant.ShopStatus.WAIT_AUDIT);
            mallShop.setApprovalStatus(ShopConstant.AuditStatus.WAIT_AUDIT);
            mallShop.setCreateTime(LocalDateTime.now());

            synchronized (ShopConstant.ShopStatus.WAIT_AUDIT) {
                Integer maxCode = shopBaseMapper.getShopCodeMax();
                if (null == maxCode){
                    mallShop.setShopCode(10000000);
                }else {
                    mallShop.setShopCode(maxCode + 1);
                }
                h2ShopBaseDao.updateById(mallShop);
            }
//            return messageServer.failMsg(ShopMessageEnum.SHOP_IS_EXIST);//已申请店铺
        }
        try {
            ipOperateStatisticsService.add(ip,1);
        }catch (Exception e){
            log.error("申请店铺 ip错误："+e);
        }
        return R.ok(mallShop.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNavyShops(List<H2ShopBase> shops) {

        synchronized (ShopConstant.ShopStatus.WAIT_AUDIT) {
            Integer maxCode = shopBaseMapper.getShopCodeMax();
            for (H2ShopBase shop : shops) {
                shop.setShopCode(maxCode++);
            }
            h2ShopBaseDao.saveBatch(shops);

        }
        //创建店铺资金账户
        List<AddShopAccount> accounts = new ArrayList<>();
        shops.stream().forEach(shop -> {
            accounts.add(new AddShopAccount().setShopId(shop.getId()).setUserId(shop.getUserId()));
        });
        financeShopAccountService.createBatch(accounts);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Long> auditPass(Long shopId) {
        H2ShopBase mallShop = h2ShopBaseDao.getById(shopId);
        if (mallShop == null) {
            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);//店铺不存在
        }
        if (!mallShop.getStatus().equals(ShopConstant.ShopStatus.WAIT_AUDIT)) {
            return messageServer.failMsg(ShopMessageEnum.STATE_HAS_CHANGED);//状态已发生改变
        }

        String contract = h2ShopContractService.build(mallShop);

        mallShop.setStatus(ShopConstant.ShopStatus.AUDIT_PASS);
        mallShop.setApprovalStatus(ShopConstant.AuditStatus.AUDITED);
        mallShop.setApprovalTime(LocalDateTime.now());
        mallShop.setApprovalBy(SecurityUtils.getUsername());
        H2ShopLevel one = h2ShopLevelDao.getOne(Wrappers.<H2ShopLevel>lambdaQuery().eq(H2ShopLevel::getUpgradeConditionNum, 0).last("limit 1"));
        if (one!=null){
            mallShop.setShopLevelId(one.getId());
        }
        boolean approve = h2ShopBaseDao.updateById(mallShop);
        EditContract editContract = new EditContract();
        editContract.setShopId(shopId);
        editContract.setShopContract(contract);
        editContract.setStatus(ShopConstant.ShopFileStatus.NO_SIGN);
        h2ShopContractService.saveOrUp(editContract);

        Executors.newFixedThreadPool(1).execute(() -> {
            H2AppUser h2AppUser=h2AppUserMapper.selectById(mallShop.getUserId());
            PushAllDeviceDTO pushAllDeviceDTO=new PushAllDeviceDTO();
            PushTitleDTO pushTitleDTO=new PushTitleDTO();
            pushTitleDTO.setChinese("恭喜 "+h2AppUser.getNickName()+" 成为新店主");
            pushTitleDTO.setEnglish("Congratulations on "+h2AppUser.getNickName()+" becoming the new store owner");
            pushAllDeviceDTO.setTitle(pushTitleDTO);
            PushUserDeviceContentDTO pushUserDeviceContentDTO=new PushUserDeviceContentDTO();
            pushUserDeviceContentDTO.setType(PushMessageTypeEnum.NOTICE_ALL);
            JSONObject json = new JSONObject();
            json.putOnce("chinese","恭喜 "+h2AppUser.getNickName()+" 成为新店主");
            json.putOnce("english","Congratulations on "+h2AppUser.getNickName()+" becoming the new store owner");
            pushUserDeviceContentDTO.setData(json.toString());
            pushAllDeviceDTO.setContent(pushUserDeviceContentDTO);
            pushUserDeviceService.pushAllUserDevice(pushAllDeviceDTO);
        });
        return R.ok();
    }

    public R auditNoPass(Long shopId, String auditDesc) {
        H2ShopBase mallShop = h2ShopBaseDao.getById(shopId);
        if (mallShop == null) {
            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);//店铺不存在
        }
        if (!mallShop.getStatus().equals(ShopConstant.ShopStatus.WAIT_AUDIT)) {
            return messageServer.failMsg(ShopMessageEnum.STATE_HAS_CHANGED);//状态已发生改变
        }
        mallShop.setStatus(ShopConstant.ShopStatus.AUDIT_NO_PASS);
        mallShop.setApprovalStatus(ShopConstant.AuditStatus.AUDIT_FAIL);

        mallShop.setApprovalTime(LocalDateTime.now());
        mallShop.setApprovalBy(SecurityUtils.getUsername());
        h2ShopBaseDao.updateById(mallShop);
        return R.ok();
    }

    @Override
    @Transactional
    public R signContract(EditContract editContract) {


        //获取合同
        H2ShopContract contract = contractDao.getByShopId(editContract.getShopId());
//        if (Objects.equals(contract.getStatus(), ShopConstant.ShopFileStatus.NO_SIGN)){
//            contract.setStatus(ShopConstant.ShopFileStatus.ONLY_CONTRACT);
//        }else if(Objects.equals(contract.getStatus(), ShopConstant.ShopFileStatus.ONLY_CERTIFICATE)){
//            contract.setStatus(ShopConstant.ShopFileStatus.SIGNED);
//        }else {
//            return messageServer.failMsg(ShopMessageEnum.SHOP_CONTRACT_STATUS_EXCEPTION);
//        }
//        if(Objects.equals(contract.getStatus(), ShopConstant.ShopFileStatus.SIGNED)){
//
//        }
        H2ShopBase mallShop = h2ShopBaseDao.getById(editContract.getShopId());
        if (!mallShop.getStatus().equals(ShopConstant.ShopStatus.AUDIT_PASS)) {
            return messageServer.failMsg(ShopMessageEnum.STATE_HAS_CHANGED_STATE);//状态已发生改变
        }
        BeanUtils.copyProperties(editContract, contract);
        contractDao.updateById(contract);
        h2ShopContractService.saveOrUp(editContract);
        toInBusiness(editContract.getShopId());
        //创建店铺资金账户
        financeShopAccountService.create(SecurityUtils.getUserId(), editContract.getShopId());
        //改变用户类型
        appUserService.becomeShopkeeper(SecurityUtils.getUserId());
        return R.ok();
    }


    private void toInBusiness(Long shopId) {
        H2ShopBase mallShop = h2ShopBaseDao.getById(shopId);
        //获取基础等级
        H2ShopLevel level = h2ShopLevelDao.getBaseLevel();
        if (level == null) {
            throw new QysException(ShopMessageEnum.SHOP_BASE_LEVEL_ERROR);
        }
        mallShop.setShopLevelId(level.getId());
        mallShop.setStatus(ShopConstant.ShopStatus.IN_BUSINESS);
        h2ShopBaseDao.updateById(mallShop);
        //升级上级用户
        //asyncService.shopUpgrade(mallShop.getUserId());//升级上级
    }

    @Override
    public R<CloseShopDto> closeShop(Long shopId) {
        H2ShopBase shopBase = h2ShopBaseDao.getById(shopId);
        if (ObjectUtils.isEmpty(shopBase)) return R.fail("system error");
        //TODO 验证订单完结
        Long orderNum = orderSkuMapper.countOrderSkusByShopId(shopId);
        //存在库存
        Integer goodNum= shopGoodsSkuStocksService.totalStockNum(shopId);
        if (goodNum > 0 || orderNum > 0) {
            CloseShopDto dto = new CloseShopDto();
            dto.setGoodsNum(goodNum);
            dto.setOrderNum(orderNum);
            return R.ok(dto, "The shop cannot be closed");
        }
        shopBase.setStatus(ShopConstant.ShopStatus.CLOSING);
        shopBase.setOffStatus(ShopConstant.AuditStatus.WAIT_AUDIT);
        //下架所有商品
        LambdaUpdateWrapper<ShopGoodsInfo> shopGoodsInfoLambdaQueryWrapper = new LambdaUpdateWrapper<>();
        shopGoodsInfoLambdaQueryWrapper.eq(ShopGoodsInfo::getShopId, shopId)
                .eq(ShopGoodsInfo::isStatus, true)
                .eq(ShopGoodsInfo::getIsDelete,1).set(ShopGoodsInfo::isStatus,false);
        shopGoodsInfoService.update(shopGoodsInfoLambdaQueryWrapper);
        return h2ShopBaseDao.updateById(shopBase) ? R.ok() : R.fail();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> closeShopApprove(Long shopId) {
        H2ShopBase shopBase = h2ShopBaseDao.getById(shopId);
        if(!Objects.equals(shopBase.getStatus(),ShopConstant.ShopStatus.CLOSING)){
            throw new QysException(ShopMessageEnum.SHOP_NOT_EXIST);
        }
        shopBase.setStatus(ShopConstant.ShopStatus.CLOSED);
        shopBase.setOffStatus(ShopConstant.AuditStatus.AUDITED);

        Long userId = shopBase.getUserId();
        H2AppUser h2AppUser = h2AppUserMapper.selectById(userId);
        if(h2AppUser.getUserType() == 3){
            h2AppUser.setUserType(2);
        } else if (h2AppUser.getUserType() == 1) {
            h2AppUser.setUserType(0);
        }
        h2AppUserMapper.updateById(h2AppUser);
        //退还保证金
        FinancePayDTO payDTO = new FinancePayDTO();
        payDTO.setUserId(Long.valueOf(shopBase.getUserId()));
        payDTO.setShopId(shopBase.getId());
        payDTO.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.RETURN_SHOP_EARNEST_MONEY));
        FinanceShopAccount account=financeShopAccountService.get(shopBase.getUserId());
        payDTO.setAmountIncurred(account.getEarnestMoney());
        payDTO.setDescription("退还保证金");
        payDTO.setBusinessType(AccountBusinessTypeEnum.RETURN_SHOP_EARNEST_MONEY);
        financeBusinessService.pay(payDTO);
        if (!payDTO.getSuccess()) {
            throw new QysException(payDTO.getMessage());
        }

        shopBase.setEarnestMoney(Constants.YesNoInt.NO);
        h2ShopBaseDao.updateById(shopBase);
        return R.ok();
    }

    @Override
    public R setPasswordByApp(EditShopPassword password) {
        if (password == null || StringUtils.isBlank(password.getPassword())) {
            return messageServer.failMsg(ExceptionEnum.PARAM_IS_ERROR);
        }
        H2ShopBase shopBase = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
        if (StringUtils.isBlank(shopBase.getPassword())) {
            shopBase.setPassword(SecurityUtils.encryptPassword(password.getPassword()));
        } else {
            if (SecurityUtils.matchesPassword(password.getOldPassword(), shopBase.getPassword())) {
                shopBase.setPassword(SecurityUtils.encryptPassword(password.getPassword()));
            } else {
                return messageServer.failMsg(ShopMessageEnum.SHOP_PASSWORD_ERROR);
            }
        }
        h2ShopBaseDao.updateById(shopBase);
        return R.ok();
    }

    @Override
    public R passwordStatus() {
//        H2ShopBase shopBase = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
//        if (null == shopBase) {
//            //店铺不存在
//            return messageServer.failMsg(ShopMessageEnum.SHOP_NOT_EXIST);
//        }
        H2AppUser user=appUserService.getById(SecurityUtils.getUserId());
        return R.ok(StringUtils.isNotBlank(user.getUserWithdrawalPassword()) ? Constants.YesNo.YES : Constants.YesNo.NO);
    }


    @Override
    public List<Long> existShopByUserIds(List<Long> userIds) {
        return h2ShopBaseDao.existByUserIds(userIds);
    }

    @Override
    public void upBatch(List<H2ShopBase> shopBases) {
        h2ShopBaseDao.updateBatchById(shopBases);
    }

    @Override
    public Boolean setShopSettlementDay(shopBaseSettlementDay shopBaseSettlementDay) {
        h2ShopBaseDao.setShopSettlementDay(shopBaseSettlementDay);
        return true;
    }

    @Override
    public R auditRefuse(Long shopId) {
        H2ShopBase mallShop = h2ShopBaseDao.getById(shopId);
        mallShop.setStatus(ShopConstant.ShopStatus.IN_BUSINESS);
        mallShop.setOffStatus(ShopConstant.AuditStatus.AUDIT_FAIL);
        h2ShopBaseDao.updateById(mallShop);
        return R.ok();
    }

    @Override
    public List<H2ShopBase> likeByShopName(String shopName) {
        return h2ShopBaseDao.getByShopName(shopName);
    }

    @Override
    public List<H2ShopBase> listByIds(List<Long> shopIds) {
        return h2ShopBaseDao.listByIds(shopIds);
    }

    @Override
    public boolean sendMessage(String phoneNumber) {
        //时间
        long now = Instant.now().getEpochSecond();

        //请求是否超过一分钟
        String code = redisCache.getCacheObject(RedisConstant.SMSSHOPPHONE + phoneNumber);
        if(StringUtils.isNotEmpty(code)){
            long time = Long.parseLong(code.split(":")[1]);
            if(now < time + 60){
                return false;
            }
        }

        // 生成一个六位的随机整数
        int min = 100000; // 最小值为100000（六位数的最小值）
        int max = 999999; // 最大值为999999（六位数的最大值）
        int randomNumber = new Random().nextInt(max - min + 1) + min;

        //发送短信
        String msg = String.format(MessageUtils.message("sms.template"), randomNumber);
        boolean result = SmsUtil.sendSms(phoneNumber, msg);
        if(result){
            redisCache.setCacheObject(RedisConstant.SMSSHOPPHONE + phoneNumber, randomNumber + ":" + now, 15L, TimeUnit.MINUTES);
            return true;
        }
        return false;
    }

    @Override
    public boolean sendMail(String mailNumber) {
        //时间
        long now = Instant.now().getEpochSecond();

        //请求是否超过一分钟
        String code = redisCache.getCacheObject(RedisConstant.MAILSHOPPHONE + mailNumber);
        if(StringUtils.isNotEmpty(code)){
            long time = Long.parseLong(code.split(":")[1]);
            if(now < time + 60){
                return false;
            }
        }

        // 生成一个六位的随机整数
        int min = 100000; // 最小值为100000（六位数的最小值）
        int max = 999999; // 最大值为999999（六位数的最大值）
        int randomNumber = new Random().nextInt(max - min + 1) + min;

        //发送短信
        String msg=languageTextService.getByLangAndTypeId("email_code_temp", LanguageEnum.EN_US.getLang());
        if (org.apache.commons.lang3.StringUtils.isNotBlank(msg)){
            HashMap params =new HashMap();
            params.put("code",randomNumber);
            ExpressionParser parser = new SpelExpressionParser();
            TemplateParserContext parserContext = new TemplateParserContext();
            msg = parser.parseExpression(msg,parserContext).getValue(params, String.class);
        }
        if (msg==null) {
            msg=MessageUtils.message("sms.template");
            msg = String.format(msg, randomNumber);
            //发送短信
        }
        MailM m=new MailM();
        m.setTitle(MessageUtils.message("shop.mail.title"));
        m.setMsg(msg);
        m.setToUsers(Arrays.asList(mailNumber));

        asyncMailClient.send(m);
        redisCache.setCacheObject(RedisConstant.MAILSHOPPHONE + mailNumber, randomNumber + ":" + now, 15L, TimeUnit.MINUTES);
         return true;
    }

    @Override
    public BigDecimal getPayableEarnestMoney() {
        H2ShopBase shop=h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());

        H2ShopLevel level=shopLevelService.getById(shop.getShopLevelId());
        FinanceShopAccount account=financeShopAccountService.get(shop.getUserId());
        if (account.getEarnestMoney()==null){
            account.setEarnestMoney(BigDecimal.ZERO);
        }
        BigDecimal payableEarnestMoney = level.getEarnestMoney().subtract(account.getEarnestMoney());
        if(payableEarnestMoney.compareTo(BigDecimal.ZERO)<0){
            payableEarnestMoney=BigDecimal.ZERO;
        }
                //shopLevelService.getPayableEarnestMoney(shop.getPayEarnestMoneyLevelId(), shop.getShopLevelId());
        return payableEarnestMoney;
    }

    @Override
    public BigDecimal getPayableEarnestMoney(Long shopId) {
        H2ShopBase shop=h2ShopBaseDao.getById(shopId);

        H2ShopLevel level=shopLevelService.getById(shop.getShopLevelId());
        FinanceShopAccount account=financeShopAccountService.get(shop.getUserId());
        if (account.getEarnestMoney()==null){
            account.setEarnestMoney(BigDecimal.ZERO);
        }
        BigDecimal payableEarnestMoney = level.getEarnestMoney().subtract(account.getEarnestMoney());
        //shopLevelService.getPayableEarnestMoney(shop.getPayEarnestMoneyLevelId(), shop.getShopLevelId());
        return payableEarnestMoney;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payEarnestMoney() {
        synchronized (SecurityUtils.getUserId()) {
            H2ShopBase shop = h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());

            H2ShopLevel level=shopLevelService.getById(shop.getShopLevelId());
            FinanceShopAccount account=financeShopAccountService.get(shop.getUserId());
            if (account.getEarnestMoney()==null){
                account.setEarnestMoney(BigDecimal.ZERO);
            }
            BigDecimal payableEarnestMoney = level.getEarnestMoney().subtract(account.getEarnestMoney());
            FinancePayDTO payDTO = new FinancePayDTO();
            payDTO.setUserId(Long.valueOf(shop.getUserId()));
            payDTO.setShopId(shop.getId());
            payDTO.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_EARNEST_MONEY));
            payDTO.setAmountIncurred(payableEarnestMoney);
            payDTO.setDescription("Earnest Money");
            payDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_EARNEST_MONEY);
            financeBusinessService.pay(payDTO);
            if (!payDTO.getSuccess()) {
                throw new QysException(payDTO.getMessage());
            }
            shop.setEarnestMoney(Constants.YesNoInt.YES);
            h2ShopBaseDao.updateById(shop);
            //是否领取注册奖励
            if(shop.getRegisterReward()==null||shop.getRegisterReward()==0){
                String rewardStr=sysConfigService.getConfigKey("shop_register_reward");
                if (rewardStr==null){
                    rewardStr="10";
                }
                FinancePayDTO rewardDTO = new FinancePayDTO();
                rewardDTO.setUserId(Long.valueOf(shop.getUserId()));
                rewardDTO.setShopId(shop.getId());
                rewardDTO.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_REGISTER_REWARD));
                rewardDTO.setAmountIncurred(new BigDecimal(rewardStr));
                rewardDTO.setDescription("Shop register reward");
                rewardDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_REGISTER_REWARD);
                financeBusinessService.pay(rewardDTO);
                if (!rewardDTO.getSuccess()) {
                    throw new QysException(rewardDTO.getMessage());
                }
                shop.setRegisterReward(Constants.YesNoInt.YES);
                h2ShopBaseDao.updateById(shop);
            }
            //是否领取升级奖励
            if (shop.getUpgradeRewardLevelId()==null){
                shop.setUpgradeRewardLevelId(-1);
            }
            if (shop.getShopLevelId()>shop.getUpgradeRewardLevelId()){
                BigDecimal reward =shopLevelService.getUpgradeReward(shop.getUpgradeRewardLevelId(),shop.getShopLevelId());
                if (reward.compareTo(new BigDecimal("0")) > 0){
                    FinancePayDTO rewardDTO = new FinancePayDTO();
                    rewardDTO.setUserId(shop.getUserId());
                    rewardDTO.setShopId(shop.getId());
                    rewardDTO.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_UPGRADE_REWARD));
                    rewardDTO.setAmountIncurred(reward);
                    rewardDTO.setDescription("Shop upgrade reward");
                    rewardDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_UPGRADE_REWARD);
                    financeBusinessService.pay(rewardDTO);
                    if (!rewardDTO.getSuccess()) {
                        throw new QysException(rewardDTO.getMessage());
                    }
                    shop.setUpgradeRewardLevelId(shop.getShopLevelId());
                    h2ShopBaseDao.updateById(shop);
                }
            }
            //上级领取邀请奖励
            if (!Objects.equals(shop.getInvitedReward(), Constants.YesNoInt.YES)){
                shopInvitedReward(shop.getUserId());
                shop.setInvitedReward(Constants.YesNoInt.YES);
                h2ShopBaseDao.updateById(shop);
            }
            //上级店铺升级
            shopUpgradation(shop.getUserId());
        }

    }

    @Override
    public List<Long> getShopIdByQuery(ShopQuery query) {
        return h2ShopBaseDao.getShopIdByQuery(query);
    }

    @Override
    public Boolean insufficientBalanceTip() {
        H2ShopBase shopBase=h2ShopBaseDao.getByUserId(SecurityUtils.getUserId());
        FinanceShopAccount account=financeShopAccountService.get(SecurityUtils.getUserId());
        H2ShopLevel level=shopLevelService.getById(shopBase.getShopLevelId());
        shopBase.getShopLevelId();
        return false;
    }

    private void shopUpgradation(Long userId){
        //获取用户
        H2AppUser user=appUserService.getById(userId.toString());
        if (user.getSuperior()==null){
            return;
        }
        //获取上级店铺
        H2ShopBase shop=h2ShopBaseDao.getByUserId(user.getSuperior());
        if (shop==null||!Objects.equals(shop.getStatus(), ShopConstant.ShopStatus.IN_BUSINESS)){
            return;
        }
        //获取上级用户的直属下级
        List<H2AppUser> users=relationService.getLowerLevels(shop.getUserId(),1);
        //有效店铺
        long count=h2ShopBaseDao.getActiveShopCount(users.stream().mapToLong(v->Long.valueOf(v.getId())).boxed().toList());
        //获取店铺上级配置
        Integer id=shopLevelService.getByUpgradeConditionNum(count);
        if (id<=shop.getShopLevelId()) {
            return;
        }
        shop.setShopLevelId(id);
        h2ShopBaseDao.updateById(shop);
        H2ShopLevelRecord record = shopLevelRecordDao.getRecord(shop.getUserId(), shop.getId(), id);
        if (record == null) {
            //增加升级记录
            record = new H2ShopLevelRecord();
            record.setShopId(shop.getId());
            record.setUserId(shop.getUserId().toString());
            record.setShopLevelId(id);
            record.setPayMoneyFlag(Constants.YesNoInt.NO);
            record.setReturnMoneyFlag(Constants.YesNoInt.NO);
            shopLevelRecordDao.save(record);
        }

    }

    private void shopInvitedReward(Long userId){
        //获取用户
        H2AppUser user=appUserService.getById(userId.toString());
        if (user.getSuperior()==null){
            return;
        }
        //获取上级店铺
        H2ShopBase shop=h2ShopBaseDao.getByUserId(user.getSuperior());
        if (shop==null||!Objects.equals(shop.getStatus(), ShopConstant.ShopStatus.IN_BUSINESS)){
            return;
        }
        String rewardStr=sysConfigService.getConfigKey("shop_invite_reward");
        if (rewardStr==null){
            rewardStr="5";
        }
        FinancePayDTO rewardDTO = new FinancePayDTO();
        rewardDTO.setUserId(shop.getUserId());
        rewardDTO.setShopId(shop.getId());
        rewardDTO.setBusinessNo(BusinessNoUtil.get(AccountBusinessTypeEnum.SHOP_INVITE_REWARD));
        rewardDTO.setAmountIncurred(new BigDecimal(rewardStr));
        rewardDTO.setDescription("Shop invite reward");
        rewardDTO.setBusinessType(AccountBusinessTypeEnum.SHOP_INVITE_REWARD);
        financeBusinessService.pay(rewardDTO);
        if (!rewardDTO.getSuccess()) {
            throw new QysException(rewardDTO.getMessage());
        }
    }

}
